﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace ModulesToolkit.DataAccess
{
    public static class Extentions
    {
        public static IEnumerable<object> AsParameters(this object obj)
        {
            foreach (var param in obj.GetType().GetProperties().Where(p => p.CanRead))
            {
                yield return param.GetValue(obj, null);
            }
        }

        public static T? ConvertTo<T>(this object obj)
            where T : struct
        {
            if (Convert.IsDBNull(obj) || obj == null)
                return null;
            return (T)obj;
        }

        public static IEnumerable<TResult> Execute<TResult>(this Database database, DbCommand command)
            where TResult : new()
        {
            IRowMapper<TResult> rowMapper = MapBuilder<TResult>.BuildAllProperties();
            IDataReader reader = database.ExecuteReader(command);
            using (reader)
            {
                while (reader.Read())
                {
                    yield return rowMapper.MapRow(reader);
                }
            }
        }

        public static IEnumerable<TResult> Execute<TResult>(this Database database, DbCommand command, object[] paramaterValues)
            where TResult : new()
        {
            database.AssignParameters(command, paramaterValues);
            return Execute<TResult>(database, command);
        }


        public static Exception Translate(this SqlException e)
        {
            Exception error;

            // uses SQLServer 2000 ErrorCodes
            switch (e.Number)
            {
                case 4060:
                    // Invalid Database
                    goto case 18456;
                case 18456:
                    // Login Failed
                    error = new SqlLoginException(e.Message, e);
                    break;
                case 547:
                    // ForeignKey Violation
                    error = new SqlForeignKeyException(e.Message, e);
                    break;
                case 2627:
                    // Unique Index/Constriant Violation
                    goto case 2601;
                case 2601:
                    // Unique Index/Constriant Violation
                    error = new SqlUniqueConstraintException(e.Message, e);
                    break;
                default:
                    // throw a general DAL Exception
                    error = new SqlBaseException(e.Message, e);
                    break;
            }

            // return the error
            return error;
        }
    }
}
